Starcor = {
    S67: {}
};


Starcor.S67.Debuger = {
    filters: [],
    filter: function(models) {
        if (models)
            filters = models.split('|');
    },
    log: function(model, info) {
        if (!this.checkFilter(model))
            return;
        this.trace('log', model, info);
    },
    info: function(model, info) {
        if (!this.checkFilter(model))
            return;
        this.trace('info', model, info);
    },
    warning: function(model, info) {
        if (!this.checkFilter(model))
            return;
        this.trace('warn', model, info);
    },
    error: function(model, info) {
        if (!this.checkFilter(model))
            return;
        this.trace('error', model, info);
    },
    trace: function(method, model, info) {
        var nowTime = Starcor.S67.$S.ftime(new Date().valueOf() / 1000, 'YYYY-MM-dd HH:mm:ss');
        if (console[method])
            console[method]("[" + nowTime + "][" + model + "]" + info);
    },
    checkFilter: function(model) {
        var bool = false;
        if (this.filters.length > 0) {
            Starcor.S67.$S.each(this.filters, function(item, num) {
                if (item == model) {
                    bool = true;
                    return true;
                }
            });
        } else {
            bool = true;
        }
        return bool;
    }
},
Starcor.S67.$S = {
    cName: function(n, parent) {
        if (!parent)
            parent = document;
        var el = [],
                _el = parent.getElementsByTagName('*');
        for (var i = 0; i < _el.length; i++) {
            var re = new RegExp('\s*' + n + '\s*');
            if (re.test(_el[i].className)) {
                el[el.length] = _el[i];
            }
        }
        return el;
    },
    //获取单位的属性值及单位
//			getNumberByAttrUnit
    nUnitAttr: function(attrValue) {
        attrValue = String(attrValue);
        var colors = __S__ColorBox.numToRGBArr(attrValue);

        if (colors) {
            //	debug(colors[0]+"|"+colors[1]+"|"+colors[2]+"|");
            return {'value': colors, 'unit': '#'};
        }

        var units = ['px', 'em'];
        var pos;
        var unit = '';
        for (var i = 0; i < units.length; i++) {
            pos = attrValue.indexOf(units[i]);
            if (pos >= 0) {
                unit = units[i];
                break;
            }
        }
        var value;
        //若为颜色 按颜色值计算
        if (unit == '#') {
            value = parseInt(attrValue.substr(1, attrValue.length), 16);

        } else {
            value = pos == -1 ? attrValue : attrValue.substr(0, pos);
        }
        return {'value': Number(value), 'unit': unit};
    },
    //获取带单位的属性值
//			getNumberByAttr
    nAttr: function(attrValue, unit) {
        attrValue = String(attrValue);
        var pos = attrValue.indexOf(unit);
        return Number(attrValue.substring(0, pos));
    },
    //获取外部CSS样式值
//			GetCurrentStyle
    currStyle: function(obj, prop) {
        if (obj.currentStyle) { //IE浏览器
            return obj.currentStyle[prop];
        } else if (window.getComputedStyle) { //W3C标准浏览器
            propprop = prop.replace(/([A-Z])/g, "-$1");
            propprop = prop.toLowerCase();
            return document.defaultView.getComputedStyle(obj, null)[propprop];
        }
        return null;
    },
    //根据ID查找子元素
//			 getChildById
    pId: function(id, parent) {
        if (!parent)
            parent = document;
        var el = [];
        var childs = parent.children;
        var len = childs.length;
        for (var i = 0; i < len; i++) {
            if (childs[i].id == id) {
                el.push(childs[i]);
            }
            else {
                if (!childs[i].children) {
                    continue;
                }
                if (childs[i].children.length == 0) {
                    continue;
                }
                el = el.concat(Starcor.S67.$S.pId(id, childs[i]));
            }
        }
        return el;
    },
    //根据类查找子元素
//			getChildByClassName
//			cName:function (classname,parent){
//				if (!parent) parent=document;
//				var el=[];
//				var childs=parent.children;
//				var len=childs.length;
//				for (var i=0;i<len;i++){
//					if (childs[i].className==classname){
//						el.push(childs[i]);	
//					}else{
//						if(!childs[i].children){
//							continue;
//						}
//						if(childs[i].children.length==0){
//							continue;
//						}
//						el=el.concat(getChildByClassName(childs[i],classname));
//					}
//				}
//				return el;
//			},
//			getChildByTagName
    Tag: function(tagname, parent) {
        if (!parent)
            parent = document;
        return parent.getElementsByTagName(tagname);
//				var el=[];
//				var childs=parent.children;
//				var len=childs.length;
//				for (var i=0;i<len;i++){
//					if (childs[i].tagName==tagname.toUpperCase()){
//						el.push(childs[i]);	
//					}else{
//						if(!childs[i].children){
//							continue;
//						}
//						if(childs[i].children.length==0){
//							continue;
//						}
//						el=el.concat($S.Tag(tagname,childs[i]));
//					}
//				}
//				return el;
    },
    f: function(name, parent) {
        var act = name.substr(0, 1);
        var func;
        switch (act) {
            case '#':
                name = name.replace('#', '');
                func = this.pId;
                break;
            case '.':
                name = name.replace('.', '');
                func = this.cName;
                break;
            default:
                func = this.Tag;
                break;
        }
        var result = [];
        if (parent instanceof Array) {
            for (var i in parent) {
                if (i == 'index')
                    continue;
                result = result.concat(func(name, parent[i]));
            }
        } else {
            result = func(name, parent);
        }
        return result;
    },
    F: function(c) {
        c = c.replace(/\s+/g, " ");
        c = c.split(' ');
        var par;
        if (c[1]) {
            par = this.f(c[1]);
        }
        if (c[0]) {
            return this.f(c[0], par);
        }
        return null;
    },
    Request: function(url) {
        var request_obj = {};
        var request_pars = {};
        var params = url.split('?');
        if (params[1]) {
            var pars = params[1].split('&');
            for (var num in pars) {
                if (typeof pars[num] == 'string') {
                    var par = pars[num].split('=');
                    request_pars[par[0]] = par[1];
                }
            }
        }
        request_obj.baseUrl = params[0];
        request_obj.params = request_pars;
        return request_obj;
    },
    each: function(arr, func, except) {
        if (!arr)
            return;
        if (typeof (arr) == "object") {
            if (arr.length) {
                for (var i = 0; i < arr.length; i++) {
                    if (func(arr[i], i))
                        break;
                }
            } else {
                for (var attr in arr) {
                    if (func(arr[attr], attr))
                        break;
                }
            }
        } else if (arr instanceof Array) {
            for (var i = 0; i < arr.length; i++) {
                if (func(arr[i], i))
                    break;
            }
        } else if (typeof (arr) == "string") {
            for (var i = 0; i < arr.length; i++) {
                if (func(arr[i], i))
                    break;
            }
        }
    },
    index: function(arr, item) {
        if (arr instanceof Array) {
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] == item) {
                    return i;
                }
            }
        } else if (typeof (arr) == "string") {
            for (var i = 0; i < arr.length; i++) {
                if (arr[i] == item) {
                    return i;
                }
            }
        }
        return -1;
    },
//			format YYYY-MM-dd HH:mm:ss
    gtime: function(date_Str, format) {
        var pos;
        var year = 0;
        var month = 0;
        var day = 0;
        var hour = 0;
        var min = 0;
        var sen = 0;
        pos = format.indexOf('YYYY');
        if (pos >= 0)
            year = date_Str.substr(pos, 4);
        pos = format.indexOf('MM');
        if (pos >= 0)
            month = parseInt(date_Str.substr(pos, 2));
        pos = format.indexOf('dd');
        if (pos >= 0)
            day = parseInt(date_Str.substr(pos, 2));
        pos = format.indexOf('HH');
        if (pos >= 0)
            hour = parseInt(date_Str.substr(pos, 2));
        pos = format.indexOf('mm');
        if (pos >= 0)
            min = parseInt(date_Str.substr(pos, 2));
        pos = format.indexOf('ss');
        if (pos >= 0)
            sen = parseInt(date_Str.substr(pos, 2));
        var date = new Date(year, month - 1, day, hour, min, sen);
        return Math.floor(date.valueOf() / 1000);

    },
//			format  YYYY-MM-dd HH:mm:ss
    ftime: function(second, format, method) {

        if (method) {
            var d = new Date();
            second = second + d.getTimezoneOffset() * 60;
        }
        var date = new Date(second * 1000);

        var year = date.getFullYear();
        var month = getDoubleStr(date.getMonth() + 1);
        var day = getDoubleStr(date.getDate());
        var hour = getDoubleStr(date.getHours());
        var munite = getDoubleStr(date.getMinutes());
        var sec = getDoubleStr(date.getSeconds());

        format = format.replace(/YYYY/, year);
        format = format.replace(/MM/, month);
        format = format.replace(/dd/, day);
        format = format.replace(/HH/, hour);
        format = format.replace(/mm/, munite);
        format = format.replace(/ss/, sec);

        return format;
        function getDoubleStr(num) {
            return Starcor.S67.$S.fnum(num, '00');
        }
    },
//			format 000.00
    fnum: function(num, format) {
        var str = num.toString();
        var strs = str.split('.');
        var formats = format.split('.');

        strs[1] = strs[1] ? strs[1] : '';
        formats[1] = formats[1] ? formats[1] : '';

        Starcor.S67.$S.each(formats[0], function(item, num) {
            if (formats[0].length < strs[0].length) {
                strs[0] = strs[0].substr(0, -formats[0].length);
                return true;
            }
            if (num >= strs[0].length) {
                strs[0] = '0' + strs[0];
            }
        });
        Starcor.S67.$S.each(formats[1], function(item, num) {
            if (formats[1].length < strs[1].length) {
                strs[1] = strs[1].substr(0, formats[1].length);
                return true;
            }
            if (num >= strs[1].length) {
                strs[1] = strs[1] + '0';
            }
        });

        if (strs[1] != '') {
            return strs[0] + "." + strs[1];
        } else {
            return strs[0];
        }

    },
    clone: function(obj) {
        var cobj;
        if (obj instanceof Array) {
            cobj = [];
        } else if (typeof (obj) == 'object') {
            cobj = {};
        } else
            return;
        Starcor.S67.$S.each(obj, function(item, attr) {
            if ((typeof (item) == 'object' || item instanceof Array) && item !== null) {
                cobj[attr] = Starcor.S67.$S.clone(item);
            } else {
                cobj[attr] = item;
            }
        });

        return cobj;
    },
    outterHTML: function(node) {
        return node.outerHTML || new XMLSerializer().serializeToString(node);
    }
};
Starcor.S67.$preLoad = function() {
    this.loadObjs = [];
    this.loadedFlag = [];
    this.elements = [];
    this.callback;
    var self = this;
    this.setCache = function(objs, func) {
        self.loadObjs = objs;
        self.callback = func;
        var len = objs.length;
        for (var i = 0; i < len; i++) {
            self.loadedFlag[i] = false;
            if (objs[i]['type'] == 'image') {
                var cacheObj = new Image();
                cacheObj.src = objs[i]['src'];
                self.elements.push(cacheObj);
                cacheObj.addEventListener('load', function(event) {
                    doObjLoaded(this);
                });
            } else if (objs[i]['type'] == 'js') {
                var js = document.createElement('script');
                var head = document.getElementsByTagName('head')[0];
                js.src = objs[i]['src'];
                head.appendChild(js);
                self.elements.push(js);
                js.onload = function(event) {
                    doObjLoaded(this);
                };
                js.onreadystatechange = function(event) {
                    if (this.readyState == 'loaded') {
                        doObjLoaded(this);
                    }
                };
            } else if (objs[i]['type'] == 'css') {
                var css = document.createElement('link');
                var head = document.getElementsByTagName('head')[0];
                css.href = objs[i]['src'];
                css.rel = 'stylesheet';
                head.appendChild(css);
                self.elements.push(css);
                var sheet, cssRules;
                if ('sheet' in css) { //FF/CM/OP
                    sheet = 'sheet';
                    cssRules = 'cssRules';
                }
                else { //IE
                    sheet = 'styleSheet';
                    cssRules = 'rules';
                }

                (function(obj) {
                    var _timer1 = setInterval(function() { // 通过定时器检测css是否加载成功

                        try {
                            if (obj[sheet] && obj[sheet][cssRules].length) { // css被成功加载
                                // console.log(link[sheet][cssRules]);

                                clearInterval(_timer1); // 清除定时器
                                clearTimeout(_timer2);
                                doObjLoaded(obj);
                                //alert('loaded, run callback'); // 加载成功执行callback
                            }
                        } catch (e) {
                            // FF看到的可能的报错：
                            //本地：nsresult: "0x8053000f (NS_ERROR_DOM_INVALID_ACCESS_ERR)" ，因为没加载完成还不能读取，加载完毕就不会报错了
                            //跨域：Security error, code: "1000" nsresult: "0x805303e8"，因为不能跨域读取CSS。。。
                            //关于跨域访问：FF/OP/CM都禁止，IE6-9都可以跨域读取css。
                        } finally {
                        }
                    }, 20);
                    // 创建超时定时器，如果过10秒没检测到加载成功
                    var _timer2 = setTimeout(function() {
                        clearInterval(_timer1); // 清除定时器
                        clearTimeout(_timer2);
                        //alert('loaded ? run callback'); // 虽然没判断加载成功也执行callback（这里可能本身就加载失败，也可能是跨域的情况）
                    }, 10000);
                })(css);

            }
        }
    };

    function doObjLoaded(obj) {
        var pos = self.elements.indexOf(obj);
        Starcor.S67.Debuger.log("preload", "[" + self.loadObjs[pos].type + "]" + self.loadObjs[pos].src + " is loaded");
        self.loadedFlag[pos] = true;
        checkLoadedAll();
    }
    ;

    function checkLoadedAll() {
        var len = self.loadedFlag.length;
        for (var i = 0; i < len; i++) {
            if (self.loadedFlag[i] == false) {
                return false;
            }
        }
        if (self.callback)
            self.callback();
        return true;
    }
    ;
};

Starcor.S67.ajax = function() {
    var self = this;
    this.timeoutID = null;
    this.httpRequest = null;
    this.callback = null;
    this.url = null;
    this.repeat = 3;
    this.repeatNum = 0;
    this.sync = true;
    this.init = function(url, callback, disSync) {
        self.sync = !disSync;
        self.callback = callback;
        self.url = url;
        self.repeatNum = 0;
        self.XHRCreate();

    };

    this.XHRCreate = function() {
        self.httpRequest = null;
        var http_request;
        if (window.XMLHttpRequest) {
            http_request = new XMLHttpRequest();
            if (http_request.overrideMimeType) {
                http_request.overrideMimeType('text/xml');
            }
        } else if (window.ActiveXObject) { // IE
            try {
                http_request = new ActiveXObject("Msxml2.XMLHTTP");
            } catch (e) {
                try {
                    http_request = new ActiveXObject("Microsoft.XMLHTTP");
                } catch (e) {
                }
            }
        }
        self.httpRequest = http_request;
        try {
            self.__S__Ajax_Cancel();
            self.timeoutID = setTimeout(
                    function() {
                        self.__S__Ajax_Timeout();
                    }, 10000);
            self.done();
        } catch (e) {
            delete self.httpRequest;
        }
    };

    this.done = function() {
        if (self.httpRequest) {
            self.httpRequest.header = '';
            self.httpRequest.aborted = true;
            self.httpRequest.abort();
            self.httpRequest.open('GET', self.url, self.sync);
            self.httpRequest.onreadystatechange = function(result) {
                if (self.httpRequest.aborted == true) {
                    self.LoadContent();
                }
            };
            self.httpRequest.send(null);
        }
    };

    this.LoadContent = function() {

        if (self.httpRequest.header == 504) {
            var obj = {};
            obj.header = 504;
            self.callback(obj);
            self.__S__Ajax_Cancel();
            return;
        }

        if (self.httpRequest.readyState != 4)
        {
            return;
        }

        if (self.httpRequest.status == 0) {
            var response_txt = self.httpRequest.responseText;
            if (response_txt.length > 0) {
                var obj = {};
                obj.header = 0;
                obj.data = response_txt;
                self.callback(obj);
                self.__S__Ajax_Cancel();
            }
            return;
        }

        if (self.httpRequest.status != 200)
        {
            var obj = {};
            obj.header = self.httpRequest.status;
            self.callback(obj);
            self.__S__Ajax_Cancel();
            return;
        }



        var response_txt = self.httpRequest.responseText;
        var obj = {};
        self.__S__Ajax_Cancel();
        try {
            obj.data = eval("(" + response_txt + ")");
            obj.header = 200;
        } catch (e) {
            obj.header = 502;
            obj.data = response_txt;
            self.callback(obj);
            return;
        }
        self.callback(obj);

    };

    this.__S__Ajax_Timeout = function() {
        self.repeatNum++;
        if (self.repeatNum < this.repeat) {
            self.__S__Ajax_Cancel();
            self.httpRequest = null;
            self.XHRCreate();
            return;
        }

        self.httpRequest.header = '504';
        self.__S__Ajax_Cancel();
        self.LoadContent(self.callback);
    };

    this.__S__Ajax_Cancel = function() {
        if (self.timeoutID) {
            clearTimeout(self.timeoutID);
            self.timeoutID = null;
        }
        self.httpRequest.aborted = true;
        self.httpRequest.abort();
    };
};




/*  
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message  
 * Digest Algorithm, as defined in RFC 1321.  
 * Version 2.1 Copyright (C) Paul Johnston 1999 - 2002.  
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet  
 * Distributed under the BSD License  
 * See http://pajhome.org.uk/crypt/md5 for more info.  
 */
Starcor.S67.MD5 = {
    hexcase: 0,
    b64pad: "",
    chrsz: 8,
    hex_md5: function(s) {
        return this.binl2hex(this.core_md5(this.str2binl(s), s.length * this.chrsz));
    },
    b64_md5: function(s) {
        return this.binl2b64(this.core_md5(this.str2binl(s), s.length * this.chrsz));
    },
    str_md5: function(s) {
        return this.binl2str(this.core_md5(this.str2binl(s), s.length * this.chrsz));
    },
    hex_hmac_md5: function(key, data) {
        return this.binl2hex(this.core_hmac_md5(key, data));
    },
    b64_hmac_md5: function(key, data) {
        return this.binl2b64(this.core_hmac_md5(key, data));
    },
    str_hmac_md5: function(key, data) {
        return this.binl2str(this.core_hmac_md5(key, data));
    },
    md5_vm_test: function()
    {
        return this.hex_md5("abc") == "900150983cd24fb0d6963f7d28e17f72";
    },
    core_md5: function(x, len)
    {
        x[len >> 5] |= 0x80 << ((len) % 32);
        x[(((len + 64) >>> 9) << 4) + 14] = len;

        var a = 1732584193;
        var b = -271733879;
        var c = -1732584194;
        var d = 271733878;

        for (var i = 0; i < x.length; i += 16)
        {
            var olda = a;
            var oldb = b;
            var oldc = c;
            var oldd = d;

            a = this.md5_ff(a, b, c, d, x[i + 0], 7, -680876936);
            d = this.md5_ff(d, a, b, c, x[i + 1], 12, -389564586);
            c = this.md5_ff(c, d, a, b, x[i + 2], 17, 606105819);
            b = this.md5_ff(b, c, d, a, x[i + 3], 22, -1044525330);
            a = this.md5_ff(a, b, c, d, x[i + 4], 7, -176418897);
            d = this.md5_ff(d, a, b, c, x[i + 5], 12, 1200080426);
            c = this.md5_ff(c, d, a, b, x[i + 6], 17, -1473231341);
            b = this.md5_ff(b, c, d, a, x[i + 7], 22, -45705983);
            a = this.md5_ff(a, b, c, d, x[i + 8], 7, 1770035416);
            d = this.md5_ff(d, a, b, c, x[i + 9], 12, -1958414417);
            c = this.md5_ff(c, d, a, b, x[i + 10], 17, -42063);
            b = this.md5_ff(b, c, d, a, x[i + 11], 22, -1990404162);
            a = this.md5_ff(a, b, c, d, x[i + 12], 7, 1804603682);
            d = this.md5_ff(d, a, b, c, x[i + 13], 12, -40341101);
            c = this.md5_ff(c, d, a, b, x[i + 14], 17, -1502002290);
            b = this.md5_ff(b, c, d, a, x[i + 15], 22, 1236535329);

            a = this.md5_gg(a, b, c, d, x[i + 1], 5, -165796510);
            d = this.md5_gg(d, a, b, c, x[i + 6], 9, -1069501632);
            c = this.md5_gg(c, d, a, b, x[i + 11], 14, 643717713);
            b = this.md5_gg(b, c, d, a, x[i + 0], 20, -373897302);
            a = this.md5_gg(a, b, c, d, x[i + 5], 5, -701558691);
            d = this.md5_gg(d, a, b, c, x[i + 10], 9, 38016083);
            c = this.md5_gg(c, d, a, b, x[i + 15], 14, -660478335);
            b = this.md5_gg(b, c, d, a, x[i + 4], 20, -405537848);
            a = this.md5_gg(a, b, c, d, x[i + 9], 5, 568446438);
            d = this.md5_gg(d, a, b, c, x[i + 14], 9, -1019803690);
            c = this.md5_gg(c, d, a, b, x[i + 3], 14, -187363961);
            b = this.md5_gg(b, c, d, a, x[i + 8], 20, 1163531501);
            a = this.md5_gg(a, b, c, d, x[i + 13], 5, -1444681467);
            d = this.md5_gg(d, a, b, c, x[i + 2], 9, -51403784);
            c = this.md5_gg(c, d, a, b, x[i + 7], 14, 1735328473);
            b = this.md5_gg(b, c, d, a, x[i + 12], 20, -1926607734);


            a = this.md5_hh(a, b, c, d, x[i + 5], 4, -378558);
            d = this.md5_hh(d, a, b, c, x[i + 8], 11, -2022574463);
            c = this.md5_hh(c, d, a, b, x[i + 11], 16, 1839030562);
            b = this.md5_hh(b, c, d, a, x[i + 14], 23, -35309556);
            a = this.md5_hh(a, b, c, d, x[i + 1], 4, -1530992060);
            d = this.md5_hh(d, a, b, c, x[i + 4], 11, 1272893353);
            c = this.md5_hh(c, d, a, b, x[i + 7], 16, -155497632);
            b = this.md5_hh(b, c, d, a, x[i + 10], 23, -1094730640);
            a = this.md5_hh(a, b, c, d, x[i + 13], 4, 681279174);
            d = this.md5_hh(d, a, b, c, x[i + 0], 11, -358537222);
            c = this.md5_hh(c, d, a, b, x[i + 3], 16, -722521979);
            b = this.md5_hh(b, c, d, a, x[i + 6], 23, 76029189);
            a = this.md5_hh(a, b, c, d, x[i + 9], 4, -640364487);
            d = this.md5_hh(d, a, b, c, x[i + 12], 11, -421815835);
            c = this.md5_hh(c, d, a, b, x[i + 15], 16, 530742520);
            b = this.md5_hh(b, c, d, a, x[i + 2], 23, -995338651);

            a = this.md5_ii(a, b, c, d, x[i + 0], 6, -198630844);
            d = this.md5_ii(d, a, b, c, x[i + 7], 10, 1126891415);
            c = this.md5_ii(c, d, a, b, x[i + 14], 15, -1416354905);
            b = this.md5_ii(b, c, d, a, x[i + 5], 21, -57434055);
            a = this.md5_ii(a, b, c, d, x[i + 12], 6, 1700485571);
            d = this.md5_ii(d, a, b, c, x[i + 3], 10, -1894986606);
            c = this.md5_ii(c, d, a, b, x[i + 10], 15, -1051523);
            b = this.md5_ii(b, c, d, a, x[i + 1], 21, -2054922799);
            a = this.md5_ii(a, b, c, d, x[i + 8], 6, 1873313359);
            d = this.md5_ii(d, a, b, c, x[i + 15], 10, -30611744);
            c = this.md5_ii(c, d, a, b, x[i + 6], 15, -1560198380);
            b = this.md5_ii(b, c, d, a, x[i + 13], 21, 1309151649);
            a = this.md5_ii(a, b, c, d, x[i + 4], 6, -145523070);
            d = this.md5_ii(d, a, b, c, x[i + 11], 10, -1120210379);
            c = this.md5_ii(c, d, a, b, x[i + 2], 15, 718787259);
            b = this.md5_ii(b, c, d, a, x[i + 9], 21, -343485551);

            a = this.safe_add(a, olda);
            b = this.safe_add(b, oldb);
            c = this.safe_add(c, oldc);
            d = this.safe_add(d, oldd);
        }
        return Array(a, b, c, d);
    },
    md5_cmn: function(q, a, b, x, s, t)
    {
        return this.safe_add(this.bit_rol(this.safe_add(this.safe_add(a, q), this.safe_add(x, t)), s), b);
    },
    md5_ff: function(a, b, c, d, x, s, t)
    {
        return this.md5_cmn((b & c) | ((~b) & d), a, b, x, s, t);
    },
    md5_gg: function(a, b, c, d, x, s, t)
    {
        return this.md5_cmn((b & d) | (c & (~d)), a, b, x, s, t);
    },
    md5_hh: function(a, b, c, d, x, s, t)
    {
        return this.md5_cmn(b ^ c ^ d, a, b, x, s, t);
    },
    md5_ii: function(a, b, c, d, x, s, t)
    {
        return this.md5_cmn(c ^ (b | (~d)), a, b, x, s, t);
    },
    core_hmac_md5: function(key, data)
    {
        var bkey = this.str2binl(key);
        if (bkey.length > 16)
            bkey = core_md5(bkey, key.length * this.chrsz);

        var ipad = Array(16), opad = Array(16);
        for (var i = 0; i < 16; i++)
        {
            ipad[i] = bkey[i] ^ 0x36363636;
            opad[i] = bkey[i] ^ 0x5C5C5C5C;
        }

        var hash = core_md5(ipad.concat(this.str2binl(data)), 512 + data.length * this.chrsz);
        return core_md5(opad.concat(hash), 512 + 128);
    },
    safe_add: function(x, y)
    {
        var lsw = (x & 0xFFFF) + (y & 0xFFFF);
        var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
        return (msw << 16) | (lsw & 0xFFFF);
    },
    bit_rol: function(num, cnt)
    {
        return (num << cnt) | (num >>> (32 - cnt));
    },
    str2binl: function(str)
    {
        var bin = Array();
        var mask = (1 << this.chrsz) - 1;
        for (var i = 0; i < str.length * this.chrsz; i += this.chrsz)
            bin[i >> 5] |= (str.charCodeAt(i / this.chrsz) & mask) << (i % 32);
        return bin;
    },
    binl2str: function(bin)
    {
        var str = "";
        var mask = (1 << this.chrsz) - 1;
        for (var i = 0; i < bin.length * 32; i += this.chrsz)
            str += String.fromCharCode((bin[i >> 5] >>> (i % 32)) & mask);
        return str;
    },
    binl2hex: function(binarray)
    {
        var hex_tab = this.hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i++)
        {
            str += hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8 + 4)) & 0xF) +
                    hex_tab.charAt((binarray[i >> 2] >> ((i % 4) * 8)) & 0xF);
        }
        return str;
    },
    binl2b64: function(binarray)
    {
        var tab = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
        var str = "";
        for (var i = 0; i < binarray.length * 4; i += 3)
        {
            var triplet = (((binarray[i >> 2] >> 8 * (i % 4)) & 0xFF) << 16)
                    | (((binarray[i + 1 >> 2] >> 8 * ((i + 1) % 4)) & 0xFF) << 8)
                    | ((binarray[i + 2 >> 2] >> 8 * ((i + 2) % 4)) & 0xFF);
            for (var j = 0; j < 4; j++)
            {
                if (i * 8 + j * 6 > binarray.length * 32)
                    str += this.b64pad;
                else
                    str += tab.charAt((triplet >> 6 * (3 - j)) & 0x3F);
            }
        }
        return str;
    }
};

